<template>
  <view class="multi-circle-progress">
    <canvas :width="size" :height="size" :style="canvasStyle" canvas-id="multiCircleCanvas"
      @touchstart="handleTouchStart" @touchmove="handleTouchMove" @touchend="handleTouchEnd"></canvas>
    <view class="center-text">
      <text class="percentage">{{ overallPercentage }}%</text>
    </view>
  </view>
</template>

<script>
// 兼容非浏览器环境
if (typeof window === 'undefined') {
  global.window = {}
  global.requestAnimationFrame = (callback) => {
    return setTimeout(callback, 16)
  }
  global.cancelAnimationFrame = (id) => {
    clearTimeout(id)
  }
}

export default {
  name: 'MultiCircleProgress',
  props: {
    // 进度数据数组
    progressData: {
      type: Array,
      default: () => []
    },
    // 画布大小
    size: {
      type: Number,
      default: 200
    },
    // 动画持续时间(ms)
    animationDuration: {
      type: Number,
      default: 1000
    },
    // 是否启用触摸交互
    interactive: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      ctx: null,
      currentProgress: [],
      startTime: 0,
      animationFrameId: null,
      isAnimating: false
    }
  },
  computed: {
    canvasStyle() {
      return {
        width: `${this.size}px`,
        height: `${this.size}px`
      }
    },
    // 计算整体百分比
    overallPercentage() {
      if (!this.progressData || !this.progressData.length) return 0;
      // 取第一个进度值作为整体百分比（健康指数）
      return Math.round(this.progressData[0].value);
    }
  },
  watch: {
    progressData: {
      handler(newVal, oldVal) {
        // 只有当数据实际变化时才重新启动动画
        // 使用简单的值比较而不是完整的对象比较
        const hasChanged = !oldVal || newVal.some((item, index) => {
          return !oldVal[index] || item.value !== oldVal[index].value;
        });

        if (hasChanged) {
          this.stopAnimation(); // 先停止当前动画
          this.initProgress(JSON.parse(JSON.stringify(newVal))); // 使用深拷贝断开引用
          this.startAnimation();
        }
      },
      deep: true,
      immediate: true
    }
  },
  mounted() {
    this.initCanvas()
    this.initProgress(this.progressData)
    this.startAnimation()
  },
  beforeDestroy() {
    this.stopAnimation()
  },
  methods: {
    // 初始化画布
    initCanvas() {
      this.ctx = uni.createCanvasContext('multiCircleCanvas', this)
    },

    // 初始化进度数据
    initProgress(progressData) {
      this.currentProgress = progressData.map(item => ({
        ...item,
        currentValue: 0
      }))
    },

    // 开始动画
    startAnimation() {
      this.stopAnimation()
      this.startTime = Date.now()
      this.isAnimating = true
      this.animate()
    },

    // 停止动画
    stopAnimation() {
      if (this.animationFrameId) {
        clearTimeout(this.animationFrameId)
        this.animationFrameId = null
      }
      this.isAnimating = false
    },

    // 动画帧
    animate() {
      const elapsed = Date.now() - this.startTime
      const progress = Math.min(elapsed / this.animationDuration, 1)

      // 更新当前进度值，使用本地副本而不是直接引用props
      this.currentProgress.forEach((item, index) => {
        if (this.progressData[index]) {
          const targetValue = this.progressData[index].value
          item.currentValue = targetValue * progress
        }
      })

      // 绘制进度
      this.drawProgress()

      // 继续动画或结束
      if (progress < 1) {
        this.animationFrameId = setTimeout(() => this.animate(), 16)
      }
    },

    // 绘制进度
    drawProgress() {
      if (!this.ctx || !this.currentProgress.length) return

      const ctx = this.ctx
      const centerX = this.size / 2
      const centerY = this.size / 2

      // 清空画布
      ctx.clearRect(0, 0, this.size, this.size)

      // 绘制背景圆
      ctx.beginPath()
      ctx.arc(centerX, centerY, this.size / 2 - 10, 0, Math.PI * 2)
      ctx.setFillStyle('#f5f5f5')
      ctx.fill()

      // 绘制每个进度圆环
      this.currentProgress.forEach((item, index) => {
        const radius = this.size / 2 - 10 - index * 15
        if (radius <= 0) return

        // 绘制背景
        ctx.beginPath()
        ctx.arc(centerX, centerY, radius, 0, Math.PI * 2)
        ctx.setStrokeStyle(item.bgColor || '#e0e0e0')
        ctx.setLineWidth(10)
        ctx.stroke()

        // 绘制进度
        if (item.currentValue > 0) {
          const endAngle = Math.PI * 2 * (item.currentValue / 100)
          ctx.beginPath()
          ctx.arc(centerX, centerY, radius, -Math.PI / 2, -Math.PI / 2 + endAngle)
          ctx.setStrokeStyle(item.color || '#4cd964')
          ctx.setLineWidth(10)
          ctx.stroke()
        }
      })

      ctx.draw()
    },

    // 触摸事件处理
    handleTouchStart(e) {
      if (!this.interactive) return
      this.touchStartX = e.touches[0].x
      this.touchStartY = e.touches[0].y
    },

    handleTouchMove(e) {
      if (!this.interactive) return
      const touchX = e.touches[0].x
      const touchY = e.touches[0].y

      // 计算触摸点与圆心的距离
      const centerX = this.size / 2
      const centerY = this.size / 2
      const distance = Math.sqrt(
        Math.pow(touchX - centerX, 2) + Math.pow(touchY - centerY, 2)
      )

      // 如果触摸点在圆内
      if (distance <= this.size / 2) {
        // 计算角度
        const angle = Math.atan2(touchY - centerY, touchX - centerX)
        // 转换为0-2π范围
        const normalizedAngle = angle < 0 ? angle + Math.PI * 2 : angle
        // 转换为0-1范围
        const progress = normalizedAngle / (Math.PI * 2)

        // 更新最外层进度
        if (this.currentProgress.length > 0) {
          this.currentProgress[0].currentValue = progress * 100
          this.drawProgress()
        }
      }
    },

    handleTouchEnd() {
      if (!this.interactive) return
      this.$emit('change', this.currentProgress[0].currentValue)
    }
  }
}
</script>

<style scoped>
.multi-circle-progress {
  position: relative;
}

.center-text {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  text-align: center;
}

.percentage {
  font-size: 24px;
  font-weight: bold;
  color: #333;
}

.label {
  font-size: 12px;
  color: #666;
  display: block;
  margin-top: 4px;
  display: inline-block;
  position: relative;
}
</style>